<?php
namespace App\Libraries\Log;

use Phalcon\Logger\Adapter\File as AdapterFile,
    Phalcon\Logger as LoggerLevel,
    Phalcon\Logger\Formatter\Line as LineFormat;

/**
 * 日志类
 * @package App\Libraries\Log
 */
class Logger {

    #region 属性

    /**
     * 日志适配器对象
     * @var \Phalcon\Logger\Adapter\File
     */
    private $logger;

    /**
     * 日志相关配置
     */
    private $config;

    /**
     * 日志入口数组
     * @var array
     */
    private $logThreshold = array();

    /**
     * 日志文件后缀
     * @var string
     */
    private $suffix;

    #endregion

    #region 构造函数

    /**
     * 文件日志帮助类构造函数
     * @param $config 日志配置信息
     * @param string $suffix 日志文件后缀
     */
    function __construct($config, $suffix = "normal") {
        $this->suffix = $suffix;
        $this->_initLoggerAdapter($config);
    }

    #endregion

    #region 写日志

    #region 事务相关

    /**
     * 开始事务
     */
    public function begin() {
        $this->logger->begin();
    }

    /**
     * 提交的内部事务
     */
    public function commit() {
        $this->logger->commit();
    }

    /**
     * 回滚的内部事务
     */
    public function rollback() {
        $this->logger->rollback();
    }

    /**
     * 关闭日志
     * @return bool
     */
    public function close() {
        $this->logger->close();
    }


    #endregion

    #region 同步方法

    /**
     * 写信息发送到日志文件
     *
     * @param mixed $type
     * @param mixed $message
     * @param array $context
     *
     */
    public function log($type = 1, $message = null, $context = null) {
        if (in_array($type, $this->logThreshold))
            $this->logger->log($type, $this->_setMessage($message), $context);
    }

    /**
     * 写一个调试消息发送到日志中
     *
     * @param string $message
     * @param array $context
     *
     */
    public function debug($message, $context = null) {
        if (in_array(LoggerLevel::DEBUG, $this->logThreshold))
            $this->logger->debug($this->_setMessage($message), $context);
    }

    /**
     * 写一个错误消息发送到日志中
     *
     * @param string $message
     * @param array $context
     *
     */
    public function error($message, $context = null) {
        if (in_array(LoggerLevel::ERROR, $this->logThreshold))
            $this->logger->error($this->_setMessage($message), $context);
    }

    /**
     * 写一个普通消息发送到日志中
     *
     * @param string $message
     * @param array $context
     *
     */
    public function info($message, $context = null) {
        if (in_array(LoggerLevel::INFO, $this->logThreshold))
            $this->logger->info($this->_setMessage($message), $context);
    }

    /**
     * 写一个通知消息发送到日志中
     *
     * @param string $message
     * @param array $context
     *
     */
    public function notice($message, $context = null) {
        if (in_array(LoggerLevel::NOTICE, $this->logThreshold))
            $this->logger->notice($this->_setMessage($message), $context);
    }

    /**
     * 写一个警告消息发送到日志中
     *
     * @param string $message
     * @param array $context
     *
     */
    public function warning($message, $context = null) {
        if (in_array(LoggerLevel::WARNING, $this->logThreshold))
            $this->logger->warning($this->_setMessage($message), $context);
    }

    /**
     * 写一个警报消息发送到日志中
     *
     * @param string $message
     * @param array $context
     *
     */
    public function alert($message, $context = null) {
        if (in_array(LoggerLevel::ALERT, $this->logThreshold))
            $this->logger->alert($this->_setMessage($message), $context);
    }

    /**
     * 写一个紧急消息发送到日志中
     *
     * @param string $message
     * @param array $context
     *
     */
    public function emergency($message, $context = null) {
        if (in_array(LoggerLevel::EMERGENCY, $this->logThreshold))
            $this->logger->emergency($this->_setMessage($message), $context);
    }

    #enndregion

    #endregion

    #region 私有方法

    /**
     * 获取日志适配器
     * @param $config 配置文件
     */
    private function _initLoggerAdapter($config) {
        //日志配置
        $this->config = $config;
        if ($this->config) {
            $this->logThreshold = $this->config->log_threshold->toArray();
            $logPath = $this->config["log_path"];
            if (!is_dir($logPath)) {
                mkdir($logPath);
            }
            $logPath .= date("Y-m");
            if (!is_dir($logPath)) {
                mkdir($logPath);
            }
            $logPath .= "/" . date("Y-m-d");
            if (!is_dir($logPath)) {
                mkdir($logPath);
            }
            $filePath = "{$logPath}/{$this->suffix}.log";
            // 文件是否存在
            $exists = file_exists($filePath);
            //　文件存在
            if ($exists) {
                $size = filesize($filePath);
                // 如果文件大于或等于1M，则将当期文件重命名。
                if ($size >= $this->config->max_size) {
                    // 获取该日志目前的文件总数
                    $count = $this->_getLogFileCount($logPath, $this->suffix);
                    $newFilePath = "{$logPath}/{$this->suffix}.{$count}.log";
                    rename($filePath, $newFilePath);
                    $exists = false;
                }
            }
            if (!$exists || !$this->logger) {
                $this->logger = new AdapterFile($filePath, array(
                    'mode' => 'a+'
                ));
                $lineFormat = new LineFormat();
                $lineFormat->setDateFormat("Y-m-d H:i:s");
                $this->logger->setFormatter($lineFormat);
            }
        }
    }

    /**
     * 设置消息
     * @param $message
     * @return string
     */
    private function _setMessage($message) {
        $url = isset($_GET["_url"]) ? $_GET["_url"] : "/";
        return "请求操作URL【{$url}】 日志内容【{$message}】";
    }

    /**
     * 获取目录下包含要匹配字符的文件总数
     * @param $dir 目录
     * @param $find 要匹配的字符
     * @return array
     */
    private function _getLogFileCount($dir, $find) {
        // 打开目录
        $handler = opendir($dir);
        $count = 0;

        // 循环的读取目录下的所有文件
        while (($filename = readdir($handler)) !== false) {
            //3、目录下都会有两个文件，名字为’.'和‘..’，不要对他们进行操作
            if ($filename != "." && $filename != ".." && strpos($filename, $find) !== false) {
                //4、进行处理
                //这里简单的用echo来输出文件名
                $count++;
            }
        }

        // 5、关闭目录
        closedir($handler);
        return $count;
    }

    #endregion

    #endregion
}
